ย - Last update: 2023-05-25

Heap ๊ด€๋ จ ์ •๋ฆฌ. Heap์€ ์ฃผ๋กœ Array๋กœ ๊ตฌํ˜„ํ•˜๋ฉฐ, ๊ฐ€์žฅ ํฐ ์•„์ดํ…œ์ด๋‚˜ ๊ฐ€์žฅ ์ž‘์€ ์•„์ดํ…œ์„ O(1)์˜ ์‹œ๊ฐ„๋ณต์žก๋„๋กœ ๊ตฌํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ด๋ฅผ ์—…๋ฐ์ดํŠธ ํ•˜๋Š”๋ฐ์— O(log n)์˜ ์‹œ๊ฐ„์ด ๊ฑธ๋ฆฌ๋Š” ์ž๋ฃŒ๊ตฌ์กฐ์ด๋‹ค. set ์ฒ˜๋Ÿผ k ๊ฐ’์„ ๊ฐ€์ง€๋Š” ์•„์ดํ…œ์„ ์ฐพ๊ฑฐ๋‚˜ ํ•  ์ˆ˜๋Š” ์—†์ง€๋งŒ, ๊ตฌ์กฐ๊ฐ€ ๋น„๊ต์  ๊ฐ„๋‹จํ•˜๋‹ˆ ์ตํ˜€๋‘๋ฉด ์ข‹๋‹ค. ๊ทธ๋ฆฌ๊ณ , ์ตœ์ ํ™”๊ฐ€ ๋งค์šฐ ๊ฐ€๋Šฅํ•œ ๋…€์„์ด๋‹ค. ์•„๋ž˜ ์ฝ”๋“œ๊ฐ€ ๋‚˜๋ฆ„์˜ ๋น„ํŠธ์—ฐ์‚ฐ์„ ์‚ฌ์šฉํ•œ ์ตœ์ ์ด๋‹ˆ ๊ผญ ์ตํ˜€๋‘๋„๋ก ํ•˜์ž.

๋ถ€๋ชจ, ์ž์‹๊ฐ„์˜ ๊ด€๊ณ„ ์ •์˜

๋งŒ์•ฝ 1-indexed Heap์„ ๊ตฌํ˜„ํ•œ๋‹ค๊ณ  ํ•˜๋ฉด, ์•„๋ž˜์ฒ˜๋Ÿผ ๋ถ€๋ชจ, ์ž์‹๊ฐ„์˜ ๊ด€๊ณ„๋ฅผ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค. (๋ฉ”๋ชจ๋ฆฌ๋Š” 1๋งŒํผ ๋‚ญ๋น„๋˜์ง€๋งŒ, Index ๊ณ„์‚ฐ์—์„œ ๋งŽ์ด ํŽธ๋ฆฌํ•˜๋‹ค)

  • ๋ถ€๋ชจ Index: idx >> 1
  • ์ž์‹ Index
    • ์™ผ์ชฝ: idx << 1
    • ์˜ค๋ฅธ์ชฝ: (idx << 1) | 1

์œ„ ๋ฐฉ์‹์œผ๋กœ ๊ฐ„๋‹จํ•˜๊ฒŒ Array๋ฅผ Tree๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

Heap์—์„œ์˜ Push

๋งŒ์•ฝ ํ˜„์žฌ์˜ Heap์˜ ํฌ๊ธฐ๊ฐ€ sz๋ผ๊ณ  ํ•˜์ž. ๊ทธ๋ ‡๋‹ค๋ฉด, ๋‹ค์Œ์— ๋“ค์–ด๊ฐˆ ์›์†Œ์˜ ์œ„์น˜๋Š” sz + 1 ์ด๋‹ค. (์ดˆ๊ธฐ ์กฐ๊ฑด์„ ์ƒ๊ฐํ•˜์ž)

์ด๋ ‡๊ฒŒ ์›์†Œ๋ฅผ ๋Œ€์ถฉ ์‚ฝ์ž…ํ•œ ์ดํ›„์—, ์ด๋ฅผ ๊ณ„์† ์ƒ์œ„ level์˜ ์•„์ดํ…œ๊ณผ ๋น„๊ตํ•˜์—ฌ, swapํ•˜๋ฉด ๋œ๋‹ค. ์•„๋ž˜๋Š” MinHeap์—์„œ์˜ ์˜ˆ์‹œ์ด๋‹ค.

T d[SZ + 1];
int sz;
void push(T v) {
int p = ++sz;
for(; p > 1; p >>= 1) {
if (d[p>>1] <= v) break; // ์ด๋ฏธ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๊ณ  ์žˆ์œผ๋ฉด break
d[p] = d[p>>1];
}
d[p] = v;
}

๋Œ€์ถฉ Insertion Sort ์™€ ๋ชจ์Šต์ด ๋น„์Šทํ•˜๋‹ˆ, ์ž˜ ์•ˆ๋˜๋ฉด ์ •๋ ฌ ์—ฐ์Šต์„ ๋‹ค์‹œ ํ•˜๊ณ  ์˜ค์ž.

Heap์—์„œ์˜ Pop

์ด๊ฒŒ ์ข€ ์–ด๋ ต๋‹ค. ์šฐ์„ , 1๋ฒˆ index์˜ ๋ฐ์ดํ„ฐ๊ฐ€ ๋น ์ ธ๋‚˜๊ฐ„๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋‚˜์„œ swap์ด ์‹œ์ž‘๋  ํ…๋ฐ, ์ตœ์ข…์ ์œผ๋กœ ์‚ฝ์ž…ํ•  ๋…€์„์€ sz ์œ„์น˜์— ์žˆ๋Š” ์•„์ดํ…œ์ด ๋  ๊ฒƒ์ด๋‹ค. ์ด๊ฒƒ์€ ์บ์‹œํ•ด์„œ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”๋‹ค. ๊ทธ๋ฆฌ๊ณ , ์ž ์žฌ์ ์œผ๋กœ ์‚ฝ์ž…๋  ์œ„์น˜๋ฅผ ์ฐพ์•„๊ฐ„๋‹ค. ๋งจ ์ฒ˜์Œ์—๋Š” c = 2์—์„œ ์‹œ์ž‘ํ•  ๊ฒƒ์ด๋‹ค. ์ขŒ์ธก ์ž์‹์œผ๋กœ swap ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•œ ์ดํ›„, ์šฐ์ธก ์ž์‹์˜ ์กฐ๊ฑด์ด ๋” ์ข‹์œผ๋ฉด ์šฐ์ธก ์ž์‹ํ•˜๊ณ  swap ํ•œ๋‹ค. ์ด๊ฒƒ์„ ๋ฐ˜๋ณตํ•˜๊ณ , ์ ์ ˆํ•œ ์‚ฝ์ž… ์œ„์น˜๊ฐ€ ์ฐพ์•„์กŒ์œผ๋ฉด, ๋„ฃ๊ณ  ๋๋‚ธ๋‹ค.

T d[SZ + 1];
int sz;
T pop() {
T r = d[1];
T val = d[sz--];
int c = 2; // ์™ผ์ชฝ ์ž์‹๋ถ€ํ„ฐ ๊ฒ€์‚ฌ
for(; c <= sz && d[c |= (c < sz && d[c] >= d[c|1])] < val; c <<= 1) {
d[c>>1] = d[c];
}
d[c>>1] = val;
return r;
}

Index๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” Heap

heap์— ์‚ฝ์ž…๋œ ์‹œ์ ์˜ Index๋ฅผ ์ €์žฅํ•ด์ฃผ๋ฉด, ํŠน์ • ์›์†Œ์˜ ๊ฐ’์„ ์ฐพ์„ ์ˆ˜ ์žˆ๊ณ , ๊ทธ Index์˜ ๊ฐ’์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ค. ๋ณ€๊ฒฝ ํ›„์—๋Š” swim๊ณผ sink๋ฅผ ์ˆœ์„œ ๊ด€๊ณ„์—†์ด 1๋ฒˆ์”ฉ ํ•ด์ฃผ๋ฉด ๋‹ค์‹œ heap์˜ ๊ตฌ์กฐ๊ฐ€ ์œ ์ง€๋œ๋‹ค. ์ด๋ฅผ ํ™œ์šฉํ•œ ์ „์ฒด heap ์ฝ”๋“œ์˜ ์ƒ˜ํ”Œ์€ ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

struct Heap {
T data[SZ + 1];
int posToID[SZ + 1]; // ์œ„์น˜ p์— ์žˆ๋Š” ๋…€์„์˜ id
int idToPos[ID_MAX]; // id๊ฐ€ ์–ด๋А ์œ„์น˜ p์— ์žˆ๋Š”์ง€
int sz;
void init() { sz = 0; }
void push(int idx, T v) {
int p = ++sz;
for(; p > 1; p >>= 1) {
if (d[p>>1] <= v) break; // ์ด๋ฏธ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๊ณ  ์žˆ์œผ๋ฉด break
d[p] = d[p>>1];
idToPos[id[p]] = idToPos[id[p>>1]];
posToID[p] = posToID[p>>1];
}
d[p] = v;
posToID[p] = idx;
idToPos[idx] = p;
}
T pop() {
T r = d[1];
int idx = posToID[sz];
T val = d[sz--];
int c = 2; // ์™ผ์ชฝ ์ž์‹๋ถ€ํ„ฐ ๊ฒ€์‚ฌ
for(; c <= sz && d[c |= (c < sz && d[c] >= d[c|1])] < val; c <<= 1) {
d[c>>1] = d[c];
idToPos[id[c>>1]] = idToPos[id[c]];
posToID[c>>1] = posToID[c];
}
d[c>>1] = val;
posToID[c>>1] = idx;
idToPos[idx] = c>>1;
return r;
}
T getData(int idx) {
return d[idToPos[idx]];
}
void updateData(int idx, T v) {
int spos = idToPos[idx];
d[spos] = v;
// ์œ„๋กœ ๊ฐฑ์‹  (swim)
int p = spos;
for(; p > 1; p >>= 1) {
if (d[p>>1] <= v) break; // ์ด๋ฏธ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๊ณ  ์žˆ์œผ๋ฉด break
d[p] = d[p>>1];
idToPos[id[p]] = idToPos[id[p>>1]];
posToID[p] = posToID[p>>1];
}
d[p] = v;
posToID[p] = idx;
idToPos[idx] = p;
// ์•„๋ž˜๋กœ ๊ฐฑ์‹  (sink)
int c = spos << 1; // ์™ผ์ชฝ ์ž์‹๋ถ€ํ„ฐ ๊ฒ€์‚ฌ
for(; c <= sz && d[c |= (c < sz && d[c] >= d[c|1])] < val; c <<= 1) {
d[c>>1] = d[c];
idToPos[id[c>>1]] = idToPos[id[c]];
posToID[c>>1] = posToID[c];
}
d[c>>1] = val;
posToID[c>>1] = idx;
idToPos[idx] = c>>1;
}
};

๊ตฌํ˜„์†๋„ ์ค‘์‹ฌ์˜ Heap

์œ„์—์„œ๋Š” ์„ฑ๋Šฅ ์ตœ์ ํ™”๋ฅผ ์ƒ๊ฐํ•˜๋ฉฐ ๊ตฌํ˜„ํ•œ heap์„ ๋ณด์•˜๋‹ค๋ฉด, ์ข€ ๋” ์ฝ”๋“œ ์ง๊ด€์ ์ธ heap์˜ ๊ตฌํ˜„์€ ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

#define parent(id) ((id) >> 1)
#define left(id) ((id) << 1)
#define right(id) (((id) << 1) | 1)
struct Heap {
int d[SZ + 1];
int sz;
void init() { sz = 0; }
void swap(int aIdx, int bIdx) {
d[aIdx] ^= d[bIdx] ^= d[aIdx] ^= d[bIdx];
}
void swim(int idx) {
int pidx = parent(idx);
if (pidx <= 0) return;
if (d[idx] >= d[pidx]) return;
swap(idx, pidx);
swim(pidx);
}
void sink(int idx) {
int cidx = left(idx);
if (cidx > sz) return;
if ((cidx|1) <= sz && d[cidx] > d[cidx|1]) cidx |= 1;
if (d[idx] <= d[cidx]) return;
swap(idx, cidx);
sink(cidx);
}
void push(int v) {
d[++sz] = v;
swim(sz - 1);
}
int pop() {
int r = d[1];
d[1] = d[sz--];
sink(1);
return r;
}
};

swim์€ ์œ„์ชฝ์œผ๋กœ ์˜ฌ๋ผ๊ฐ€๋Š” ๋ชจ์Šต์ด๊ณ , sink๋Š” ๊ฐ€๋ผ์•‰๋Š” ๋ชจ์Šต์—์„œ ์ด๋ฆ„์ด ๋ถ™์—ˆ๋‹ค. ๋‹ค๋งŒ ์žฌ๊ท€๋กœ ๊ตฌํ˜„ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— O2์™€ ๊ฐ™์€ ์ปดํŒŒ์ผ ์˜ต์…˜์ด ๋ถ™์ง€ ์•Š๋Š”๋‹ค๋ฉด ์ผ๋ฐ˜ ๋ฃจํ”„๋กœ ๊ตฌํ˜„ํ•œ ๊ฒƒ๋ณด๋‹ค ํ™•์‹คํžˆ ๋А๋ฆฌ๋‹ค.

Time Complexity

  • Push: O(logโกn)O(\log n)
  • Pop: O(logโกn)O(\log n)
  • Top: O(1)O(1)
๐Ÿท๏ธ ์ฃผ์ œ ๋ชฉ๋ก: